import React, {
  useState, createContext, useContext, useRef, useEffect, memo, forwardRef
} from 'react'
import {
  Table, Form, Input, InputNumber, Tooltip, Checkbox
} from 'antd'
import { cloneDeep, isEqual } from 'lodash'
import styled from 'styled-components'

const StyledTable = styled(Table)`
.editable-cell-value-wrap {
  cursor: text;
}
.ant-table-cell {
  cursor: default;
}
`

const EditableContext = createContext(null)

/**
 *
 * @param {*} props
 * @returns
 */
function ATable(props) {
  function EditableRow({ index, ...props }, ref) {
    const [form] = Form.useForm()
    return (
      <Form form={form} component={false}>
        <EditableContext.Provider value={form}>
          {
            // virtual是dom为div，为了防止报错
            virtual ? <div {...props} /> : <tr {...props} />
          }
        </EditableContext.Provider>
      </Form>
    )
  }

  function EditableCell({
    title,
    editable,
    editor,
    children,
    dataIndex,
    record,
    handleSave,
    ...restProps
  }, ref) {
    const [editing, setEditing] = useState(false)
    const inputRef = useRef()
    const form = useContext(EditableContext)
    useEffect(() => {
      if (editing) {
        inputRef.current.focus()
      }
    }, [editing])

    const toggleEdit = () => {
      setEditing(!editing)
      form.setFieldsValue({
        [dataIndex]: record[dataIndex]
      })
    }

    const save = async () => {
      try {
        const values = await form.validateFields()
        toggleEdit()
        handleSave({ ...record, ...values })
      } catch (errInfo) {
        console.log('Save failed:', errInfo)
      }
    }
    const editorEle = {
      input: <Input
        size={size}
        ref={inputRef}
        onPressEnter={save}
        onBlur={() => toggleEdit()}
      />,
      inputNumer: <InputNumber
        size={size}
        ref={inputRef}
        onPressEnter={save}
        onBlur={() => toggleEdit()}
      />
    }
    let childNode = children

    if (editable) {
      childNode = editing ? (
        <Form.Item
          style={{
            margin: 0
          }}
          name={dataIndex}
        >
          {editorEle[editor || 'input']}
        </Form.Item>
      ) : (
        <div
          className="editable-cell-value-wrap"
          onClick={toggleEdit}
        >
          {children}
        </div>
      )
    }

    return virtual ? <div {...restProps}>{childNode}</div> : <td {...restProps}>{childNode}</td>
  }
  const {
    virtual = false,
    scroll = {},
    columns, rowKey = 'id', loading = false, data = [], total = 0, onChange,
    pageNo,
    pageSize,
    showSizeChanger = true,
    pagination,
    size = 'small',
    selectedId = [],
    setSelectedId = () => { },
    ...params
  } = props

  const onTitleCheckboxChange = (checked) => {
    if (checked) {
      let next = cloneDeep(selectedId)
      const dataIds = data.map((r) => r[rowKey])
      next = [...next, ...dataIds]
      next = Array.from(new Set(next))
      setSelectedId(next)
    } else {
      setSelectedId(selectedId.filter((r) => !data.map((r2) => r2[rowKey]).includes(r)))
    }
  }

  const onCheckboxChange = (checked, record) => {
    if (checked) {
      setSelectedId([...selectedId, record[rowKey]])
    } else {
      setSelectedId(selectedId.filter((r) => r !== record[rowKey]))
    }
  }

  const _columns = columns.map((r) => {
    if (r.type === 'checkbox') {
      return {
        title: <Checkbox
          checked={selectedId.length && selectedId.length === data.length}
          indeterminate={selectedId.length > 0 && selectedId.length !== data.length}
          onChange={(e) => onTitleCheckboxChange(e.target.checked)}
        />,
        dataIndex: 'checkbox',
        width: 50,
        render: (data, record) => (
          <Checkbox
            checked={selectedId.includes(record[rowKey])}
            onChange={(e) => onCheckboxChange(e.target.checked, record)}
          />
        ),
        ...r
      }
    }
    if (r.tooltip === false) {
      return {
        width: 100,
        ellipsis: true,
        render: (data) => {
          if (data) return data
          return '-'
        },
        ...r
      }
    }
    return {
      width: 100,
      render: (data) => (
        <Tooltip
          placement="topLeft"
          title={data}
        >
          {data || '-'}
        </Tooltip>
      ),
      ellipsis: {
        showTitle: false
      },
      ...r
    }
  })

  return (
    <StyledTable
      components={{
        body: {
          row: forwardRef(EditableRow),
          cell: forwardRef(EditableCell)
        }
      }}
      loading={{
        spinning: loading
      }}
      size={size}
      dataSource={data}
      columns={_columns}
      rowKey={(record) => record[rowKey]}
      pagination={pagination || {
        current: pageNo,
        pageSize,
        total,
        showSizeChanger,
        size: 'default',
        showTotal: (num) => `共${num}条`,
        onChange
      }}
      virtual={virtual}
      scroll={scroll}
      {
        ...params
      }
    />
  )
}
// 使用isEqual处理，否则传入的值必须使用useMemo或者useState存储，比如scroll
export default memo(ATable, isEqual)
